﻿using System.ServiceModel;

namespace NGeo.Yahoo.PlaceFinder
{
    public sealed class PlaceFinderClient : ClientBase<IInvokePlaceFinderServices>, IConsumePlaceFinder
    {
        public Results Geocode(Request request)
        {
            EnsureContractsAreSatisfied(request);

            Response response;

            if (!string.IsNullOrWhiteSpace(request.Location))
                response = Channel.GeocodeByLocation(request.Location,
                    request.Locale, request.Start, request.Count,
                    request.OffsetMeters, request.GetFlagsAsString(), request.GetGFlagsAsString(), request.AppId);

            else if (!string.IsNullOrWhiteSpace(request.Name))
                response = Channel.GeocodeByName(request.Name,
                    request.Locale, request.Start, request.Count,
                    request.OffsetMeters, request.GetFlagsAsString(), request.GetGFlagsAsString(), request.AppId);

            else if (request.WoeId.HasValue)
                response = Channel.GeocodeByWoeId(request.WoeId.Value,
                    request.Locale, request.Start, request.Count,
                    request.OffsetMeters, request.GetFlagsAsString(), request.GetGFlagsAsString(), request.AppId);

            else if (!string.IsNullOrWhiteSpace(request.Line1)
                || !string.IsNullOrWhiteSpace(request.Line2)
                || !string.IsNullOrWhiteSpace(request.Line3))
                response = Channel.GeocodeByAddressLines(request.Line1, request.Line2, request.Line3, request.Locale,
                    request.Start, request.Count, request.OffsetMeters,
                    request.GetFlagsAsString(), request.GetGFlagsAsString(), request.AppId);

            else
                response = Channel.GeocodeByOther(request.HouseNumber, request.StreetName, request.UnitType, request.Unit, 
                    request.CrossStreet, request.Postal, request.Level4, request.Level3, request.Level2, request.Level1, 
                    request.Level0, request.Locale, request.Start, request.Count, request.OffsetMeters,
                    request.GetFlagsAsString(), request.GetGFlagsAsString(), request.AppId);

            var results = (response != null && response.Results != null && response.Results.Items != null)
                ? response.Results
                : null;

            return results;
        }

        public Results ReverseGeocode(ReverseRequest request)
        {
            EnsureContractsAreSatisfied(request);

            if (!request.GFlags.Contains(RequestGFlag.Reverse))
                request.GFlags.Add(RequestGFlag.Reverse);

            var response = Channel.ReverseGeocode(request.ReverseQuery, request.Locale,
                request.Start, request.Count, request.OffsetMeters,
                request.GetFlagsAsString(), request.GetGFlagsAsString(), request.AppId);

            var results = (response != null && response.Results != null && response.Results.Items != null) 
                ? response.Results 
                : null;

            return results;
        }

        private static void EnsureContractsAreSatisfied(Request request)
        {
            if (request.Flags.Contains(RequestFlag.StreetDetail))
                request.Flags.Remove(RequestFlag.StreetDetail);

            if (!request.Flags.Contains(RequestFlag.Json))
                request.Flags.Add(RequestFlag.Json);

            if (request.Flags.Contains(RequestFlag.Php))
                request.Flags.Remove(RequestFlag.Php);

        }

    }
}
